using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;

namespace Charisma.Conventions
{
    public class NamedKeyMemberConvention : IKeyMemberConvention
    {
        private const string KeyMemberName = "id";
        private static readonly StringComparer comparer = StringComparer.OrdinalIgnoreCase;

        #region IKeyMemberConvention Members

        public MemberInfo Find(Type type, IEnumerable<MemberInfo> candidates)
        {
            string pattern = KeyMemberName;
            var result = Find(pattern, candidates);
            if (result != null)
                return result;

            pattern = "_" + KeyMemberName;
            result = Find(pattern, candidates);
            if (result != null)
                return result;

            string typeName = type.Name;
            if (type.IsGenericType)
            {
                type = type.GetGenericTypeDefinition();
                Contract.Assume(type != null);
                int i = typeName.IndexOf('`');
                typeName = i < 0 ? typeName : typeName.Substring(0, i);
            }

            pattern = string.Format("{0}{1}", typeName, KeyMemberName);
            result = Find(pattern, candidates);
            if (result != null)
                return result;

            pattern = string.Format("{0}_{1}", typeName, KeyMemberName);
            result = Find(pattern, candidates);
            if (result != null)
                return result;

            return null;
        }

        #endregion

        private static MemberInfo Find(string pattern, IEnumerable<MemberInfo> candidates)
        {
            Contract.Requires(candidates != null);
            return candidates.Where(c => comparer.Compare(pattern, c.Name) == 0).FirstOrDefault();
        }
    }
}